﻿using System.Collections.Immutable;
using System.Diagnostics;
using DimensionsHelper.LanguageService.Protocol;

namespace DimensionsHelper.LanguageService.Syntax;

public class ClassSignature : ObjectTypeSignature
{
    private SyntaxList<ConstantSignature>? _constants;

    private SyntaxList<QualifiedName>? _implements;

    internal ClassSignature(SyntaxToken declareKeywordToken, Identifier name, SyntaxNode? parent) :
        base(SyntaxKinds.ClassSignature, declareKeywordToken, name, parent)
    {
    }


    internal override void SetUri(DocumentUri uri)
    {
        base.SetUri(uri);
        _implements?.SetUri(uri);
        _constants?.SetUri(uri);
    }


    /// <summary>
    ///     获取实现的接口限定名列表
    /// </summary>
    public IReadOnlyList<QualifiedName> GetImplementInterfaces()
    {
        return _implements == null ? new List<QualifiedName>() : _implements;
    }


    /// <summary>
    ///     获取已添加的常量定义
    /// </summary>
    public ImmutableArray<ConstantSignature> GetConstants()
    {
        return _constants == null
            ? ImmutableArray<ConstantSignature>.Empty
            : _constants.ToImmutableArray();
    }


    /// <summary>
    ///     查找指定名称的常量定义，如果指定名称不存在，返回<see langword="null" />
    /// </summary>
    /// <param name="name">查找的名称，不区分大小写</param>
    public ConstantSignature? GetConstant(string name)
    {
        return FindDeclaration(_constants, name);
    }


    /// <summary>
    ///     添加一个实现的接口的全限定名
    /// </summary>
    public void Implement(QualifiedName name)
    {
        AddChildMember(ref _implements, name);
    }

    /// <summary>
    ///     添加一个类常量签名
    /// </summary>
    /// <param name="constant"></param>
    public void AddConstant(ConstantSignature constant)
    {
        AddChildMember(ref _constants, constant);
        constant.ContainingClass = this;
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        base.AcceptVisitor(visitor);
        AcceptList(visitor, _constants);
        AcceptList(visitor, _implements);
    }
}


public static partial class NodeFactory
{
    public static ClassSignature CreateClassSignature(SyntaxNode? parent, SyntaxToken declareKeywordToken,
        Identifier identifierName, IEnumerable<QualifiedName>? inherits, IEnumerable<QualifiedName>? implements,
        IEnumerable<PropertySignature>? properties, IEnumerable<MethodSignature>? methods,
        IEnumerable<ConstantSignature>? constants)
    {
        Debug.Assert(declareKeywordToken.IsNode(SyntaxKinds.ClassKeywordToken));
        ClassSignature signature = new(declareKeywordToken, identifierName, parent);

        if (inherits != null)
        {
            foreach (QualifiedName name in inherits)
            {
                signature.Inherit(name);
            }
        }

        if (implements != null)
        {
            foreach (QualifiedName name in implements)
            {
                signature.Implement(name);
            }
        }

        if (properties != null)
        {
            foreach (PropertySignature property in properties)
            {
                signature.AddProperty(property);
            }
        }

        if (methods != null)
        {
            foreach (MethodSignature method in methods)
            {
                signature.AddMethod(method);
            }
        }

        if (constants != null)
        {
            foreach (ConstantSignature constant in constants)
            {
                signature.AddConstant(constant);
            }
        }

        return signature;
    }
}